/*
 * Copyright ©2021 su binglun(9085309@qq.com). All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *---------------------------------------------------------------------
 *-                                                                   -
 *-           Website : http://phoenix.sunny360.cn/                   -
 *-                                                                   -
 *---------------------------------------------------------------------
 */
package cn.sunny360.core.handler.http;

import cn.sunny360.core.common.PhResult;
import cn.sunny360.core.service.UserService;
import cn.sunny360.core.utils.Container;
import cn.sunny360.core.utils.JsonUtil;
import cn.sunny360.messsage.MsgRequest;
import cn.sunny360.messsage.MsgResult;
import io.vertx.core.Promise;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

public class UserHandler extends HttpBaseHandler {

	private static final Logger logger = LoggerFactory.getLogger(UserHandler.class);

	private UserService userService;

	public UserHandler() {
		this.userService = Container.getComponent(UserService.class);
	}

	public void apiUserLogin(RoutingContext context) {
		logger.debug("用户准备登录");
		String contentType = context.request().getHeader("Content-Type");
		logger.debug(contentType);
		if (StringUtils.isNotBlank(contentType) && contentType.contains("application/octet-stream")) {
			Buffer body = context.getBody();
			MsgRequest msgLogin = MsgRequest.newInstance();
			msgLogin.parseByteArray(body.getBytes());

			if (StringUtils.isBlank(msgLogin.getUserName())
					|| StringUtils.isBlank(msgLogin.getPassword())) {
				MsgRequest loginResult = MsgRequest.newInstance()
						.setType(400)
						.setMessage("请求参数不完整，参数中必须包含用户名、密码！");
				context.response().setStatusCode(200)
						.putHeader("content-type", "application/octet-stream;charset=utf-8")
						.end(Buffer.buffer().appendBytes(loginResult.toByteArray()));
				return;
			}
			logger.debug("开始用户名、密码校验");
			Promise<JsonObject> loginPromise = Promise.promise();
			userService.doLogin(new JsonObject(msgLogin.toJson()), loginPromise);
			loginPromise.future()
				.onSuccess(rsUser->{
					logger.debug("用户名密码校验通过");
					//记录登录日志
					addLoginLog(rsUser.getLong("user_id"), msgLogin, Promise.promise());
					// 响应结果
					JsonObject data = new JsonObject()
							.put("user_id", rsUser.getString("user_id"))
							.put("username", rsUser.getString("username"))
							.put("nick_name", rsUser.getString("nick_name"))
							.put("head_img", rsUser.getString("head_img"))
							.put("address", rsUser.getString("address"))
							.put("sex", rsUser.getString("sex"))
							.put("token", rsUser.getString("token"));
					MsgResult result = MsgResult.newInstance()
							.setStatus(200)
							.setMsg("OK")
							.setData(data.toString());
					context.response().setStatusCode(200)
							.putHeader("content-type", "application/octet-stream;charset=utf-8")
							.end(Buffer.buffer().appendBytes(result.toByteArray()));
				}).onFailure(e->{
					badResult(context, e);
					logger.error("登陆失败，发生异常！", e);
				});
		} else {
			badRequest(context, new Exception("请求参数错误"));
		}
	}

	public void addLoginLog(Long userId, MsgRequest msgLogin, Promise<PhResult> promise) {
		JsonObject logInfo = new JsonObject()
				.put("user_id", userId);
		try {
			String ext = msgLogin.getExt();
			JsonObject extInfo = new JsonObject(ext);
			logInfo.put("device_id", extInfo.getString("device_id"))
					.put("location", extInfo.getString("location"))
					.put("longitude", extInfo.getString("longitude"))
					.put("latitude", extInfo.getString("latitude"));
		} catch (Exception e) {
			logger.warn("ext 信息解析出错");
		}
		userService.addLoginLog(logInfo, promise);
	}

	public void getOnlineList(RoutingContext context) {

		String contentType = context.request().getHeader("Content-Type");
		logger.debug(contentType);
		if (StringUtils.isNotBlank(contentType) && contentType.contains("application/octet-stream")) {
			Buffer body = context.getBody();
			MsgRequest user = MsgRequest.newInstance();
			user.parseByteArray(body.getBytes());
			// 取用户id
			long userId = Long.parseLong(user.getUserId());
			// 取token
			String token = user.getToken();
			Promise<String> promise = Promise.promise();
			userService.getTokenByUserId(userId, promise);
			promise.future()
				.onSuccess(resultToken->{
					logger.debug("请求中的token：" + token);
					logger.debug("数据库中查询到的token：" + resultToken);
					//校验token是否正确
					if (resultToken.equals(token)) {
						Promise<JsonArray> userListPromise = Promise.promise();
						userService.getOnlineUserList(userId, userListPromise);
						userListPromise.future()
								.onSuccess(userList->{
									okResult(context, "OK", JsonUtil.toStrVal(userList).toString());
								})
								.onFailure(e->{
									badResult(context, e);
								});
					} else {
						logger.error("token错误", new Exception("token错误"));
						badResult(context, new Exception("token错误"));
					}
				})
				.onFailure(e->{
					logger.error("", e);
					badResult(context, e);
				});
		} else {
			logger.error("参数格式不正确");
			internalError(context, new Exception("参数格式不正确"));
		}
	}

	/**
	 * 根据用户id查询用户信息
	 * @param context
	 */
	public void getUserInfoById(RoutingContext context) {
		String userId = context.pathParam("id");
		Promise<JsonObject> promise = Promise.promise();
		userService.getUserInfoById(Long.parseLong(userId), promise);
		promise.future()
				.onSuccess(u->{
					okResult(context, "OK", JsonUtil.toStrVal(u).toString());
				})
				.onFailure(e->{
					logger.error("查询用户信息失败", e);
					badResult(context, e);
				});
	}

	public void getUserInfoByName(RoutingContext context) {
		String username = context.pathParam("username");
		if (StringUtils.isBlank(username)) {
			badResult(context, new Exception("参数错误！"));
			return;
		}
		Promise<JsonObject> promise = Promise.promise();
		userService.getUserInfoByName(username, promise);
		promise.future()
				.onSuccess(u->{
					okResult(context, "OK", JsonUtil.toStrVal(u).toString());
				})
				.onFailure(e->{
					badResult(context, e);
				});

	}

	public void createUser(RoutingContext context) {
		MsgRequest msgRequest = MsgRequest.newInstance();
		msgRequest.parseByteArray(context.getBody().getBytes());
		String ext = msgRequest.getExt();
		JsonObject userInfo = new JsonObject(ext);
		Promise<PhResult> promise = Promise.promise();
		userService.createUser(userInfo, promise);
		promise.future()
				.onSuccess(result->{
					okResult(context, result);
				})
				.onFailure(e->{
					badResult(context, e);
				});
	}

	public void getUserListByRole(RoutingContext context) {
		String roleId = context.pathParam("roleId");
		if (StringUtils.isBlank(roleId)) {
			badResult(context, new Exception("参数错误！"));
			return;
		}
		Promise<List<JsonObject>> promise = Promise.promise();
		userService.getUserListByRole(Long.parseLong(roleId), promise);
		promise.future()
				.onSuccess(list->{
					okResult(context, "OK", JsonUtil.toStrVal(new JsonArray(list)).toString());
				})
				.onFailure(e->{
					badResult(context, e);
				});
	}

	public void updateUser(RoutingContext context) {
		MsgRequest msgRequest = MsgRequest.newInstance();
		msgRequest.parseByteArray(context.getBody().getBytes());
		String ext = msgRequest.getExt();
		JsonObject userInfo = new JsonObject(ext);
		if (StringUtils.isNotBlank(msgRequest.getUserId())) {
			userInfo.put("user_id", Long.parseLong(msgRequest.getUserId()));
		}
		Promise<PhResult> promise = Promise.promise();
		userService.updateUser(userInfo, promise);
		promise.future()
				.onSuccess(result->{
					okResult(context, result);
				})
				.onFailure(e->{
					badResult(context, e);
				});
	}
}
